﻿using System;
using System.Configuration;
using System.IO;
using SimpleServiceBus.Bus.Pipeline;
using SimpleServiceBus.Configuration;
using SimpleServiceBus.Endpoint;
using SimpleServiceBus.Endpoint.Management.Monitoring;
using SimpleServiceBus.Endpoint.Metadata;
using SimpleServiceBus.EndpointManagement.Server.Configuration;
using SimpleServiceBus.Endpoints.DotNetServiceBus.Configuration;
using SimpleServiceBus.Endpoints.Msmq.Configuration;
using SimpleServiceBus.Endpoints.Rhino.Configuration;
using SimpleServiceBus.Messages.Management.Monitoring;
using SimpleServiceBus.Messages.Subscriptions;
using SimpleServiceBus.Tests.Bus.MessageManagement;
using SimpleServiceBus.Tests.Stubs;
using NUnit.Framework;
using NUnit.Framework.SyntaxHelpers;

namespace SimpleServiceBus.Tests.Config
{
    [TestFixture]
    public class ConfigurationTestFixture
    {
        private static System.Configuration.Configuration GetTestConfiguration(string configFile)
        {
            var map = new ExeConfigurationFileMap
                          {
                              ExeConfigFilename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, configFile)
                          };

            return ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
        }

        [Test]
        public void EndpointConfigurationSectionAndAssemblyNameConfig()
        {
            System.Configuration.Configuration cfg = GetTestConfiguration("TestMsmqApp.config");
            Assert.That(cfg, SyntaxHelper.Not.Null);

            var epConfig = cfg.GetSection("endpoint") as EndpointConfiguration;
            Assert.That(epConfig, SyntaxHelper.Not.Null);
            Assert.That(epConfig.EndpointID, Is.EqualTo("myEndPoint"));
            Assert.That(epConfig.Name, Is.EqualTo("ThisIsMyNameDontWearItOut"));
            Assert.That(epConfig.ReturnAddress, Is.EqualTo("myEndPoint"));
            Assert.That(epConfig.EndpointLatitude, Is.EqualTo(-121.34));
            Assert.That(epConfig.EndpointLongitude, Is.EqualTo(32.432));
            Assert.That(epConfig.MessageHandlerAssemblies.Count, Is.EqualTo(1));
            Assert.That(epConfig.MessageHandlerAssemblies[0].Assembly, Is.EqualTo(typeof (MessagingEndpoint).Assembly));
            Assert.That(epConfig.Description, Is.EqualTo("HaHa"));
            Assert.That(epConfig.SupportEmailAddress, Is.EqualTo("support"));
            Assert.That(epConfig.DistributorAddress, Is.EqualTo("distributor"));
            Assert.That(epConfig.PoisonMessageAddress, Is.EqualTo("poison"));
            Assert.That(epConfig.MaxMessageRetryCount, Is.EqualTo(5));
            Assert.That(epConfig.SupportTelephoneNumber, Is.EqualTo("supportPhone"));
            Assert.That(epConfig.NumberOfWorkerThreads, Is.EqualTo(1));
            Assert.That(epConfig.MaxRetries, Is.EqualTo(1));
            Assert.That(epConfig.IncomingMessageLoggingLevel,Is.EqualTo(MessageLoggingLevel.HeadersOnly));
            Assert.That(epConfig.OutgoingMessageLoggingLevel,Is.EqualTo(MessageLoggingLevel.HeadersAndBody));
            Assert.That(epConfig.SendOnly, Is.EqualTo(true));

            Assert.That(epConfig.StatusReportInterval, Is.EqualTo(TimeSpan.FromMinutes(5)));
            Assert.That(epConfig.StatusReportGracePeriod, Is.EqualTo(TimeSpan.FromMinutes(1)));
            Assert.That(epConfig.MonitorServiceAddress, Is.EqualTo("monitor"));
            Assert.That(epConfig.StatusProbes.Count, Is.EqualTo(2));

            IEndpointStatusProbe p1 = epConfig.StatusProbes[0].CreateProbeFromConfiguration();
            Assert.That(p1, SyntaxHelper.Not.Null);
            Assert.That(p1.Name, Is.EqualTo("myProbe"));
            Assert.That(p1.UnitOfMeasurement, Is.EqualTo("TestUnit"));
            Assert.That(p1.DataType, Is.EqualTo(MeasurementDataType.Text));
            Assert.That(((TestStatusProbe) p1).TestCustomProperty, Is.EqualTo(DateTime.Parse("08/04/1976 3:32 AM")));
            Assert.That(((TestStatusProbe) p1).TestCustomProperty2, Is.EqualTo("HaHa I Am A Test"));

            var p2 = epConfig.StatusProbes[1].CreateProbeFromConfiguration() as PerfCounterProbe;
            Assert.That(p2, SyntaxHelper.Not.Null);
            Assert.That(p2.Category, Is.EqualTo("Memory"));
            Assert.That(p2.Counter, Is.EqualTo("Available MBytes"));
            Assert.That(p2.Instance, Is.EqualTo(String.Empty));
            Assert.That(Double.Parse(p2.TakeMeasurement(null).Value), Is.GreaterThan(0.0));

            Assert.That(epConfig.MessageHandlerAssemblies.Count, Is.EqualTo(1));
            Assert.That(epConfig.MessageHandlerAssemblies[0].Name, Is.EqualTo("SimpleServiceBus"));
            Assert.That(epConfig.MessageHandlerAssemblies[0].Assembly,Is.SameAs(typeof(MessagingEndpoint).Assembly));

            Assert.That(epConfig.MessageAssemblies.Count, Is.EqualTo(1));
            Assert.That(epConfig.MessageAssemblies[0].Name, Is.EqualTo("SimpleServiceBus.Messages"));
            Assert.That(epConfig.MessageAssemblies[0].Assembly, Is.SameAs(typeof (SubscriptionMessage).Assembly));
            Assert.That(epConfig.MessageAssemblies[0].DestinationAddress, Is.EqualTo("destination"));

            Assert.That(epConfig.MessageFilters.Count, Is.EqualTo(1));
            Assert.That(epConfig.MessageFilters[0].Name, Is.EqualTo("TestFilter"));
            Assert.That(epConfig.MessageFilters[0].Enabled, Is.EqualTo(true));
            Assert.That(epConfig.MessageFilters[0].FilterExpression, Is.EqualTo("This=\"that\""));
            Assert.That(epConfig.MessageFilters[0].FilterDirection, Is.EqualTo("receive"));
            Assert.That(epConfig.MessageFilters[0].MessageType,Is.EqualTo(typeof(Message_A)));

            Assert.IsNotNull(epConfig.Profiler);
            Assert.That(epConfig.Profiler.Enabled, Is.False);
            Assert.That(epConfig.Profiler.ProfilePipelineComponents, Is.EqualTo(true));
            Assert.That(epConfig.Profiler.PipelineDirection, Is.EqualTo(PipelineDirection.Send));

            var mqConfig = epConfig as MsmqEndpointConfiguration;
            Assert.That(mqConfig.Msmq, Is.Not.Null);
            Assert.That(mqConfig.Msmq.DestinationQueueIsTransactional, Is.EqualTo(true));
            Assert.That(mqConfig.Msmq.ReceiveQueueIsTransactional, Is.EqualTo(false));
            Assert.That(mqConfig.Msmq.PurgeOnStartup, Is.EqualTo(false));
            Assert.That(mqConfig.Msmq.InputQueue, Is.EqualTo("MyInputQueue"));
        }


        [Test]
        public void MonitorServerConfig()
        {
            System.Configuration.Configuration cgf = GetTestConfiguration("TestMsmqApp.config");

            var scfg = cgf.GetSection("endpointMonitorServer") as EndpointMonitorConfiguration;
            Assert.That(scfg, SyntaxHelper.Not.Null);
            Assert.That(scfg.StatusBroadcastInterval, Is.EqualTo(TimeSpan.FromMinutes(1)));
            Assert.That(scfg.EndpointMonitorInterval, Is.EqualTo(TimeSpan.FromMinutes(1)));
            Assert.That(scfg.SmtpHostName, Is.EqualTo("localhost"));
            Assert.That(scfg.SmtpPort, Is.EqualTo(50));
            Assert.That(scfg.EmailFromAddress, Is.EqualTo("support@mycompany.com"));
            Assert.That(scfg.WebServiceUri, Is.EqualTo("http://localhost:8989"));
        }

        [Test]
        public void RhinoConfig()
        {
            System.Configuration.Configuration cfg = GetTestConfiguration("TestRhinoApp.config");
            Assert.That(cfg, SyntaxHelper.Not.Null);

            var epConfig = cfg.GetSection("endpoint") as EndpointConfiguration;
            Assert.That(epConfig, Is.Not.Null);

            var config = epConfig as RhinoEndpointConfiguration;
            Assert.That(config.Rhino, Is.Not.Null);
            Assert.That(config.Rhino.QueueUri, Is.EqualTo("localhost"));
            Assert.That(config.Rhino.InputQueueName, Is.EqualTo("inputQueue"));
            Assert.That(config.Rhino.PoisonQueueName, Is.EqualTo("poisonQueue"));
            Assert.That(config.Rhino.QueueStoragePath, Is.EqualTo("here.i.am"));
        }

        [Test]
        public void AzureConfig()
        {
            System.Configuration.Configuration cfg = GetTestConfiguration("TestAzureApp.config");
            Assert.That(cfg, Is.Not.Null);

            var epConfig = cfg.GetSection("endpoint") as EndpointConfiguration;
            Assert.That(epConfig, Is.Not.Null);

            var config = epConfig as AzureEndpointConfiguration;
            Assert.That(config.DotNetServiceBusQueue, Is.Not.Null);
            Assert.That(config.DotNetServiceBusQueue.InputQueueName, Is.EqualTo("inputQueue"));
            Assert.That(config.DotNetServiceBusQueue.PoisonQueueName, Is.EqualTo("poisonQueue"));
            Assert.That(config.DotNetServiceBusQueue.SolutionName, Is.EqualTo("solution-name"));
            Assert.That(config.DotNetServiceBusQueue.SolutionPassword, Is.EqualTo("solution-password"));
            Assert.That(config.DotNetServiceBusQueue.SendTimeOut, Is.EqualTo(TimeSpan.FromDays(1)));
            Assert.That(config.DotNetServiceBusQueue.ReceiveTimeOut, Is.EqualTo(TimeSpan.FromHours(1)));
        }
    }
}